﻿using System;
using System.Collections.Generic;
using UnityEngine;
using Object = UnityEngine.Object;

namespace EntityKit.Runtime
{
    /// <summary>
    /// GameObject对象池
    /// </summary>
    public sealed class GameObjectPool
    {
        private GameObject _spawnTem;
        private Queue<GameObject> _objectQueue = new Queue<GameObject>();
        private Action<GameObject> _onSpawn;
        private Action<GameObject> _onDespawn;
        private int _limit = 100;

        /// <summary>
        /// 对象数量
        /// </summary>
        public int Count => _objectQueue.Count;

        public GameObjectPool(GameObject spawnTem, int limit, Action<GameObject> onSpawn, Action<GameObject> onDespawn)
        {
            _spawnTem = spawnTem;
            _limit = limit > 0 ? limit : 100;
            _onSpawn = onSpawn;
            _onDespawn = onDespawn;
        }

        /// <summary>
        /// 生成对象
        /// </summary>
        /// <returns>对象</returns>
        public GameObject Spawn()
        {
            GameObject obj;
            if (_objectQueue.Count > 0)
            {
                obj = _objectQueue.Dequeue();
            }
            else
            {
                obj = Object.Instantiate(_spawnTem);
            }

            _onSpawn?.Invoke(obj);
            obj.SetActive(true);
            return obj;
        }

        /// <summary>
        /// 回收对象
        /// </summary>
        /// <param name="obj">对象</param>
        public void Despawn(GameObject obj)
        {
            if (obj == null)
                return;

            if (_objectQueue.Count >= _limit)
            {
                _onDespawn?.Invoke(obj);
                Object.Destroy(obj);
            }
            else
            {
                obj.SetActive(false);
                _onDespawn?.Invoke(obj);
                _objectQueue.Enqueue(obj);
            }
        }

        /// <summary>
        /// 清空所有对象
        /// </summary>
        public void Clear()
        {
            while (_objectQueue.Count > 0)
            {
                GameObject obj = _objectQueue.Dequeue();
                if (obj)
                {
                    Object.Destroy(obj);
                }
            }

            _objectQueue.TrimExcess();
        }

        /// <summary>
        /// 预加载指定数量的对象
        /// </summary>
        /// <param name="count">预加载数量</param>
        public void Preload(int count)
        {
            var currentCount = _objectQueue.Count;
            var spaceAvailable = _limit - currentCount;
            var preloadCount = Math.Min(count, spaceAvailable);

            for (int i = 0; i < preloadCount; i++)
            {
                var obj = Object.Instantiate(_spawnTem);
                obj.SetActive(false);
                _objectQueue.Enqueue(obj);
            }
        }
    }
}